/*     */ package com.zimbra.cs.index;
/*     */ 
/*     */ import com.google.common.collect.ImmutableSet;
/*     */ import com.google.common.collect.ImmutableSet.Builder;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.mailbox.Mailbox;
/*     */ import java.io.IOException;
/*     */ import java.util.ArrayList;
/*     */ import java.util.Iterator;
/*     */ import java.util.List;
/*     */ import java.util.Set;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public final class UnionQueryOperation
/*     */   extends CombiningQueryOperation
/*     */ {
/*  38 */   private boolean atStart = true;
/*  39 */   private ZimbraHit cachedNextHit = null;
/*     */   
/*     */   public long getCursorOffset()
/*     */   {
/*  43 */     return -1L;
/*     */   }
/*     */   
/*     */   Set<QueryTarget> getQueryTargets()
/*     */   {
/*  48 */     ImmutableSet.Builder<QueryTarget> builder = ImmutableSet.builder();
/*  49 */     for (QueryOperation op : this.operations) {
/*  50 */       builder.addAll(op.getQueryTargets());
/*     */     }
/*  52 */     return builder.build();
/*     */   }
/*     */   
/*     */   public void resetIterator() throws ServiceException
/*     */   {
/*  57 */     if (!this.atStart) {
/*  58 */       for (Iterator<QueryOperation> iter = this.operations.iterator(); iter.hasNext();) {
/*  59 */         QueryOperation q = (QueryOperation)iter.next();
/*  60 */         q.resetIterator();
/*     */       }
/*  62 */       this.cachedNextHit = null;
/*  63 */       internalGetNext();
/*     */     }
/*     */   }
/*     */   
/*     */   public ZimbraHit getNext() throws ServiceException
/*     */   {
/*  69 */     this.atStart = false;
/*  70 */     ZimbraHit toRet = this.cachedNextHit;
/*     */     
/*  72 */     if (this.cachedNextHit != null) {
/*  73 */       this.cachedNextHit = null;
/*  74 */       internalGetNext();
/*     */     }
/*     */     
/*  77 */     return toRet;
/*     */   }
/*     */   
/*     */   public ZimbraHit peekNext()
/*     */   {
/*  82 */     return this.cachedNextHit;
/*     */   }
/*     */   
/*     */   private void internalGetNext() throws ServiceException {
/*  86 */     if (this.cachedNextHit == null) {
/*  87 */       if (this.context.getResults().getSortBy() == SortBy.NONE) {
/*  88 */         for (QueryOperation op : this.operations) {
/*  89 */           this.cachedNextHit = op.getNext();
/*  90 */           if (this.cachedNextHit != null) {
/*  91 */             return;
/*     */           }
/*     */           
/*     */         }
/*     */       }
/*     */       else
/*     */       {
/*  98 */         int currentBestHitOffset = -1;
/*  99 */         ZimbraHit currentBestHit = null;
/* 100 */         for (int i = 0; i < this.operations.size(); i++) {
/* 101 */           QueryOperation op = (QueryOperation)this.operations.get(i);
/* 102 */           if (op.hasNext()) {
/* 103 */             if (currentBestHitOffset == -1) {
/* 104 */               currentBestHitOffset = i;
/* 105 */               currentBestHit = op.peekNext();
/*     */             } else {
/* 107 */               ZimbraHit opNext = op.peekNext();
/* 108 */               int result = opNext.compareTo(this.context.getResults().getSortBy(), currentBestHit);
/* 109 */               if (result < 0)
/*     */               {
/* 111 */                 currentBestHitOffset = i;
/* 112 */                 currentBestHit = opNext;
/*     */               }
/*     */             }
/*     */           }
/*     */         }
/* 117 */         if (currentBestHitOffset > -1) {
/* 118 */           this.cachedNextHit = ((QueryOperation)this.operations.get(currentBestHitOffset)).getNext();
/* 119 */           assert (this.cachedNextHit == currentBestHit);
/*     */         }
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   public void close()
/*     */     throws IOException
/*     */   {
/* 128 */     for (QueryOperation op : this.operations) {
/* 129 */       op.close();
/*     */     }
/*     */   }
/*     */   
/*     */   public boolean hasSpamTrashSetting()
/*     */   {
/* 135 */     for (QueryOperation op : this.operations) {
/* 136 */       if (!op.hasSpamTrashSetting()) {
/* 137 */         return false;
/*     */       }
/*     */     }
/* 140 */     return true;
/*     */   }
/*     */   
/*     */   void forceHasSpamTrashSetting()
/*     */   {
/* 145 */     for (QueryOperation op : this.operations) {
/* 146 */       op.forceHasSpamTrashSetting();
/*     */     }
/*     */   }
/*     */   
/*     */   QueryTarget getQueryTarget(QueryTarget targetOfParent) {
/* 151 */     return targetOfParent;
/*     */   }
/*     */   
/*     */   boolean hasNoResults()
/*     */   {
/* 156 */     return false;
/*     */   }
/*     */   
/*     */   boolean hasAllResults()
/*     */   {
/* 161 */     return false;
/*     */   }
/*     */   
/*     */   QueryOperation expandLocalRemotePart(Mailbox mbox) throws ServiceException
/*     */   {
/* 166 */     List<QueryOperation> newList = new ArrayList();
/* 167 */     for (QueryOperation op : this.operations) {
/* 168 */       newList.add(op.expandLocalRemotePart(mbox));
/*     */     }
/* 170 */     this.operations = newList;
/* 171 */     return this;
/*     */   }
/*     */   
/*     */   QueryOperation ensureSpamTrashSetting(Mailbox mbox, boolean includeTrash, boolean includeSpam) throws ServiceException
/*     */   {
/* 176 */     List<QueryOperation> newList = new ArrayList(this.operations.size());
/* 177 */     for (QueryOperation op : this.operations) {
/* 178 */       if (!op.hasSpamTrashSetting()) {
/* 179 */         newList.add(op.ensureSpamTrashSetting(mbox, includeTrash, includeSpam));
/*     */       } else {
/* 181 */         newList.add(op);
/*     */       }
/*     */     }
/* 184 */     assert (newList.size() == this.operations.size());
/* 185 */     this.operations = newList;
/* 186 */     return this;
/*     */   }
/*     */   
/*     */   public void add(QueryOperation op)
/*     */   {
/* 191 */     this.operations.add(op);
/*     */   }
/*     */   
/*     */   void pruneIncompatibleTargets(Set<QueryTarget> targets)
/*     */   {
/* 196 */     for (int i = this.operations.size() - 1; i >= 0; i--) {
/* 197 */       QueryOperation op = (QueryOperation)this.operations.get(i);
/* 198 */       if ((op instanceof UnionQueryOperation)) {
/* 199 */         if (!$assertionsDisabled) throw new AssertionError();
/* 200 */         ((UnionQueryOperation)op).pruneIncompatibleTargets(targets);
/* 201 */       } else if ((op instanceof IntersectionQueryOperation)) {
/* 202 */         ((IntersectionQueryOperation)op).pruneIncompatibleTargets(targets);
/*     */       } else {
/* 204 */         Set<QueryTarget> set = op.getQueryTargets();
/* 205 */         assert (set.size() <= 1);
/* 206 */         if ((set.isEmpty()) || ((!targets.containsAll(set)) && (!set.contains(QueryTarget.UNSPECIFIED)))) {
/* 207 */           this.operations.remove(i);
/*     */         }
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   public QueryOperation optimize(Mailbox mbox)
/*     */     throws ServiceException
/*     */   {
/* 216 */     for (int i = 0;; i++) { if (i >= this.operations.size()) break label101;
/* 217 */       QueryOperation op = (QueryOperation)this.operations.get(i);
/* 218 */       QueryOperation optimized = op.optimize(mbox);
/* 219 */       if ((optimized == null) || ((optimized instanceof NoTermQueryOperation))) {
/* 220 */         this.operations.remove(i);
/* 221 */       } else if (op != optimized) {
/* 222 */         this.operations.remove(i);
/* 223 */         this.operations.add(optimized);
/* 224 */         break;
/*     */       }
/*     */     }
/*     */     
/*     */     label101:
/*     */     
/* 230 */     if (this.operations.isEmpty()) {
/* 231 */       return new NoTermQueryOperation();
/*     */     }
/*     */     
/*     */     label274:
/* 235 */     for (int i = 0;; i++) { if (i >= this.operations.size()) break label280;
/* 236 */       QueryOperation lhs = (QueryOperation)this.operations.get(i);
/*     */       
/*     */ 
/*     */ 
/*     */ 
/* 241 */       if ((lhs instanceof UnionQueryOperation)) {
/* 242 */         combineOps(lhs, true);
/* 243 */         this.operations.remove(i);
/* 244 */         break;
/*     */       }
/*     */       
/* 247 */       for (int j = i + 1;; j++) { if (j >= this.operations.size()) break label274;
/* 248 */         QueryOperation rhs = (QueryOperation)this.operations.get(j);
/* 249 */         QueryOperation joined = lhs.combineOps(rhs, true);
/* 250 */         if (joined != null) {
/* 251 */           this.operations.remove(j);
/* 252 */           this.operations.remove(i);
/* 253 */           this.operations.add(joined);
/* 254 */           break;
/*     */         }
/*     */       }
/*     */     }
/*     */     
/*     */ 
/*     */     label280:
/*     */     
/* 262 */     if (this.operations.size() == 1) {
/* 263 */       return (QueryOperation)this.operations.get(0);
/*     */     }
/*     */     
/* 266 */     return this;
/*     */   }
/*     */   
/*     */   String toQueryString()
/*     */   {
/* 271 */     StringBuilder out = new StringBuilder("(");
/*     */     
/* 273 */     boolean atFirst = true;
/*     */     
/* 275 */     for (QueryOperation op : this.operations) {
/* 276 */       if (!atFirst) {
/* 277 */         out.append(" OR ");
/*     */       }
/* 279 */       out.append(op.toQueryString());
/* 280 */       atFirst = false;
/*     */     }
/* 282 */     return ')';
/*     */   }
/*     */   
/*     */   public String toString()
/*     */   {
/* 287 */     StringBuilder out = new StringBuilder("UNION{");
/*     */     
/* 289 */     boolean atFirst = true;
/*     */     
/* 291 */     for (QueryOperation op : this.operations) {
/* 292 */       if (atFirst) {
/* 293 */         atFirst = false;
/*     */       } else {
/* 295 */         out.append(" OR ");
/*     */       }
/* 297 */       out.append(op);
/*     */     }
/* 299 */     return '}';
/*     */   }
/*     */   
/*     */   public Object clone()
/*     */   {
/* 304 */     assert (this.cachedNextHit == null);
/* 305 */     UnionQueryOperation result = (UnionQueryOperation)super.clone();
/* 306 */     result.operations = new ArrayList(this.operations.size());
/* 307 */     for (QueryOperation op : this.operations) {
/* 308 */       result.operations.add((QueryOperation)op.clone());
/*     */     }
/* 310 */     return result;
/*     */   }
/*     */   
/*     */   protected QueryOperation combineOps(QueryOperation other, boolean union)
/*     */   {
/* 315 */     if ((union) && ((other instanceof UnionQueryOperation))) {
/* 316 */       this.operations.addAll(((UnionQueryOperation)other).operations);
/* 317 */       return this;
/*     */     }
/* 319 */     return null;
/*     */   }
/*     */   
/*     */   protected void begin(QueryOperation.QueryContext ctx) throws ServiceException
/*     */   {
/* 324 */     assert (this.context == null);
/* 325 */     this.context = ctx;
/* 326 */     for (QueryOperation op : this.operations) {
/* 327 */       ZimbraLog.search.debug("Executing: %s", new Object[] { op });
/*     */       
/* 329 */       op.begin(new QueryOperation.QueryContext(ctx.getMailbox(), ctx.getResults(), ctx.getParams(), ctx.getChunkSize() + 1));
/*     */     }
/* 331 */     internalGetNext();
/*     */   }
/*     */   
/*     */   public List<QueryInfo> getResultInfo()
/*     */   {
/* 336 */     List<QueryInfo> result = new ArrayList();
/* 337 */     for (QueryOperation op : this.operations) {
/* 338 */       result.addAll(op.getResultInfo());
/*     */     }
/* 340 */     return result;
/*     */   }
/*     */   
/*     */   protected void depthFirstRecurse(QueryOperation.RecurseCallback cb)
/*     */   {
/* 345 */     for (QueryOperation op : this.operations) {
/* 346 */       op.depthFirstRecurse(cb);
/*     */     }
/* 348 */     cb.recurseCallback(this);
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/index/UnionQueryOperation.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */